package comm.utill;

import comm.net.protocol.Protobuf;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by junxin on 2018/7/8.
 */
public class Param implements Cloneable {
    public Param() {
        this(false);
    }

    public Param(boolean mapMode) {
        m_map = new HashMap<String, Object>();
    }

    public void clear() {
        m_map.clear();
    }

    public Param setInt(String key, Integer value){
        return setObject(key, value);
    }

    public Integer getInt(String key) {
        Object value = getObject(key);
        if (value == null) {
            return null;
        }
        // 由于parseJson时只能根据是否有小数点来判断是转成int还是double，因此这里做个特殊处理
        if (value instanceof Double) {
            return ((Double)value).intValue();
        }
        if (value instanceof Long) {
            return ((Long)value).intValue();
        }
        return (Integer) value;
    }

    public Param setString(String key, String value) {
        return setObject(key, value);
    }

    public String getString(String key) {
        Object value = getObject(key);
        if (value == null) {
            return null;
        }
        return (String)value;
    }

    public Param setBoolean(String key, boolean value) {
        return setObject(key, value);
    }

    public Boolean getBoolean(String key) {
        Object value = getObject(key);
        if (value == null) {
            return null;
        }
        return (Boolean)value;
    }

    public Param setParam(String key, Param value){
        return setObject(key, (Param)value);
    }

    public Param getParam(String key){
        Object value = getObject(key);
        if (value == null) {
            return null;
        }
        return (Param) value;
    }


    public Param setObject(String key, Object value) {
        if ((key == null) || (value == null)) {
            return null;
        }

        m_map.put(key, value);
        return this;
    }

    public Object getObject(String key) {
        if (key == null) {
            return null;
        }
        return m_map.get(key);
    }

    public Object getObject(String key, Object defaultValue) {
        Object value = getObject( key );
        if( value == null ){
            return defaultValue;
        }
        return value;
    }



    public HashMap<String, Protobuf.Model> encoding() {
        return encoding(null);
    }
    // 编码
    public HashMap<String, Protobuf.Model> encoding(HashMap<String, Object> _map) {
        HashMap<String, Protobuf.Model> map = new HashMap<String, Protobuf.Model>();

        if (_map == null) {
            _map = m_map;
        }

        for (Map.Entry<String, Object> entry : _map.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value instanceof String) {
                map.put(key, Protobuf.Model.newBuilder().setType(Var.Type.STRING).setString((String) value).build());
            }
            if (value instanceof Integer) {
                map.put(key, Protobuf.Model.newBuilder().setType(Var.Type.INT).setInt((Integer) value).build());
            }
            if (value instanceof Boolean) {
                map.put(key, Protobuf.Model.newBuilder().setType(Var.Type.BOOLEAN).setBoolean((Boolean) value).build());
            }
            if (value instanceof Param) {
                map.put(key, Protobuf.Model.newBuilder().setType(Var.Type.PARAM).putAllParam(encoding(((Param) value).m_map)).build());
            }
        }
        return map;
    }

    // 解码
    public static Param decodeing(Map<String, Protobuf.Model> map) {
        Param param = new Param();

        for(Map.Entry<String, Protobuf.Model> entry: map.entrySet()) {
            String key = entry.getKey();
            Protobuf.Model value = entry.getValue();

            switch (value.getType()){
                case Var.Type.INT: param.setInt(key, value.getInt()); break;
                case Var.Type.STRING: param.setString(key, value.getString()); break;
                case Var.Type.BOOLEAN: param.setBoolean(key, value.getBoolean()); break;
                case Var.Type.PARAM: param.setParam(key, Param.decodeing(value.getParamMap()));
            }
        }
        return param;
    }

    public String toString() {
        return toJson();
    }

    public String toJson() {
        StringBuilder buf = new StringBuilder(512);
        toJson(buf);
        return buf.toString();
    }

    public void toJson(StringBuilder buf) {
        buf.append("{");
        int count = 0;
        for (Map.Entry<String, Object> entry : m_map.entrySet()) {
            count++;
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value == null) {
                buf.setLength(0);
                buf.append("{}");
                return;
            }
            buf.append("\"");
            buf.append(key);
            buf.append("\":");
            Var.toJson(buf, value);
            if (count < m_map.size()) {
                buf.append(",");
            }
        }
        buf.append("}");
    }


    private HashMap<String, Object> m_map;				// 特殊模式，例如resin初始化加载配置文件使用些模式
}
